﻿//----------------------------------------------------------------
// Desc: 用于 STL 标准的内存配器
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2010-06-11
//
// Update Date :
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


extern FAPI void* FMemAlloc(size_t size, FNEW_FUNC);
extern FAPI bool FMemFree(void*& mem);


template < typename _Ty >
class FAllocator
{
public:
    typedef FAllocator<_Ty>  allocate_type;
    typedef _Ty                 value_type;
    typedef value_type*         pointer;
    typedef value_type&         reference;
    typedef const value_type*   const_pointer;
    typedef const value_type&   const_reference;
    typedef size_t              size_type;
    typedef ptrdiff_t           difference_type;

    template <typename _Other>
    struct rebind
    {
        typedef FAllocator<_Other> other;
    };
    ACHAR *_Charalloc(size_type _Count)
    {	// allocate _Count bytes
        return ((ACHAR *)allocate(_Count));
    }
    void _Chardealloc(void *_Ptr, size_type _Count)
    {	// deallocate _Count bytes
        if (_Ptr != 0)
            deallocate(_Ptr, _Count);
    }

    bool operator==(const allocate_type&)
    {   // test for allocator equality (always true)
        return (true);
    }
    bool operator!=(const allocate_type&)
    {   // test for allocator inequality (always false)
        return (false);
    }
    pointer address(reference _Val) const
    {   // return address of mutable _Val
        return (&_Val);
    }
    const_pointer address(const_reference _Val) const
    {   // return address of nonmutable _Val
        return (&_Val);
    }
    FAllocator()
    {   // construct default FAllocator (do nothing)
    }
    FAllocator(const FAllocator<_Ty>&)
    {   // construct by copying (do nothing)
    }
    template <typename _Other>
    FAllocator(const FAllocator<_Other>&)
    {   // construct from a related FAllocator (do nothing)
    }
    template <typename _Other>
    FAllocator<_Ty>& operator=(const FAllocator<_Other>&)
    {   // assign from a related FAllocator (do nothing)
        return (*this);
    }
    void deallocate(pointer _Ptr, size_type)
    {   // deallocate object at _Ptr, ignore size
        void* p = (void*)_Ptr;
        FFree(p);
    }
    pointer allocate(size_type _Count)
    {   // allocate array of _Count elements
        return (pointer)FMemAlloc(_Count * sizeof(_Ty), _FFILEA_, _FLINEA_, _FTA("FAllocator::allocate"), _FTA("FAllocator"));
    }
    pointer allocate(size_type _Count, const void*)
    {   // allocate array of _Count elements, ignore hint
        return (allocate(_Count));
    }
    void construct(pointer _Ptr, const _Ty& _Val)
    {   // construct object at _Ptr with value _Val
        FNewPT(_Ptr, _Ty)(_Val);
    }
    void destroy(pointer _Ptr)
    {   // destroy object at _Ptr
        if (_Ptr)
            (_Ptr)->~_Ty();
    }
    size_t max_size() const
    {   // estimate maximum array size
        size_t _Count = (size_t)(-1) / sizeof (_Ty);
        return (0 < _Count ? _Count : 1);
    }
};

template<typename _T1, typename _T2>
inline bool operator==(const FAllocator<_T1>&, const FAllocator<_T2>&)
{ return true; }

template<typename _Tp>
inline bool operator==(const FAllocator<_Tp>&, const FAllocator<_Tp>&)
{ return true; }

template<typename _T1, typename _T2>
inline bool operator!=(const FAllocator<_T1>&, const FAllocator<_T2>&)
{ return false; }

template<typename _Tp>
inline bool operator!=(const FAllocator<_Tp>&, const FAllocator<_Tp>&)
{ return false; }